package com.hiv.client;

import com.hiv.client.model.weixin.WeixinJsCreateOrderReq;
import com.hiv.client.model.weixin.WeixinJsCreateOrderRes;
import com.hiv.client.model.weixin.WeixinQueryOrderRes;
import com.hiv.utils.FastJsonUtils;
import com.hiv.client.model.weixin.WeixinJsRefundOrderReq;
import com.hiv.client.model.weixin.WeixinJsRefundOrderRes;
import com.hiv.common.enums.ErrorCode;
import com.hiv.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;

/**
 * jsapi支付: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
 */
@Slf4j
@Component
public class WeixinJsClient {

    @Autowired(required = false)
    private CloseableHttpClient httpClient;

    /**
     * 下预支付单
     *
     * @throws Exception
     */
    public WeixinJsCreateOrderRes createOrder(WeixinJsCreateOrderReq req) throws Exception {
        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        StringEntity entity = new StringEntity(FastJsonUtils.toJSONString(req), Charset.forName("UTF-8"));
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("success,return body = " + EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                log.info("success");
            } else {
                log.info("failed,resp code : {} ,return body : {}", statusCode, EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return FastJsonUtils.fromJSONString(EntityUtils.toString(response.getEntity()), WeixinJsCreateOrderRes.class);
    }

    /**
     * 查询订单可通过微信支付订单号或商户订单号两种方式查询，两种查询方式返回结果相同
     *
     * @throws Exception
     */
    public WeixinQueryOrderRes queryOrder(String outTradeNo, String mchid) throws IOException, URISyntaxException {
        //请求URL
        URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo);
        uriBuilder.setParameter("mchid", mchid);

        //完成签名并执行请求
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpGet);

        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) { //处理成功
                log.info("WeixinJsClient.queryOrder success,return body: {}", EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) { //处理成功，无返回Body
                log.info("WeixinJsClient.queryOrder success");
            } else {
                log.error("WeixinJsClient.queryOrder failed,resp code: {}, ,return body = {}", statusCode, EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
            return FastJsonUtils.fromJSONString(EntityUtils.toString(response.getEntity()), WeixinQueryOrderRes.class);
        } catch (Exception e) {
            log.error("WeixinJsClient.queryOrder err: {}", e.getMessage(), e);
            throw new BusinessException(ErrorCode.ERR_REMOTE_INVOKE, e);
        } finally {
            if (response != null) {
                response.close();
            }
        }
    }

    /**
     * 申请退款
     *
     * @return
     * @throws URISyntaxException
     * @throws IOException
     */
    public WeixinJsRefundOrderRes createRefundOrder(WeixinJsRefundOrderReq req) throws URISyntaxException, IOException {
        //请求URL
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
        StringEntity entity = new StringEntity(FastJsonUtils.toJSONString(req), Charset.forName("UTF-8"));
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求response = {HttpResponseProxy@13463} "HttpResponseProxy{HTTP/1.1 400 Bad Request [Server: nginx, Date: Sat, 09 Apr 2022 16:16:04 GMT, Content-Type: application/json; charset=utf-8, Connection: keep-alive, Keep-Alive: timeout=8, Cache-Control: no-cache, must-revalidate, X-Content-Type-Options: nosniff, Request-ID: 08C4E2C6920610D40418C4C6EEA30620B17A28FECD01-268435463, Content-Language: zh-CN, Wechatpay-Nonce: bc378f09d2dd8e7329e5741baa2662b6, Wechatpay-Signature: z7ObEt0gk1OTxYNcnlKSbGRZLNL/byY6H5ytO5v28UMat3E8OzgOuCX6uKV2xYGtjlKlBJgvYyQY4NDa0NDPudPefDsoo31CQxMl3UA63Bef1fCiT7riyJUg39e72dYK0IwqqbU9ZG50C79MTUBstUeeTKSH4GYk9KdksA31ccXUa8QfEvHGHHnwdf3ugU4FfEqHxGbX/wEOWasldfHM2kUsdV4PshhovcwU9IL5ABjfGFmvt+/+ox98mFWTf8zpC1/IqJ0cfiuxzCaWT4BMJ3I4F4KzxHCsZBnp9umxZtrmwPGzBpYzg/oIBQUQ0TU3MFrNcQy2W7MbkKOXeqYkTw==, Wechatpay-Timestamp: 1649520964, Wechatpay-Serial: 427882A9B800B93FD34F115967A2F39B002E0AFD, Wechatpay-Signature-Type: WECHATPAY2-SHA256-RSA2048] org.apache.http.client.entity.DecompressingEntity@38ffc727}"
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("success,return body = " + EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                log.info("success");
            } else {
                log.info("failed,resp code : {} ,return body : {}", statusCode, EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
        } finally {
            if (response != null) {
                response.close();
            }
        }
        return FastJsonUtils.fromJSONString(EntityUtils.toString(response.getEntity()), WeixinJsRefundOrderRes.class);
    }
}
